using System;
using System.Collections.Generic;
using System.Linq;
using SimpleJSON;
using UnityEngine;

namespace Gj
{
    internal class EasyAction
    {
        public Action On;
        public Action<JSONArray> OnArr;
        public Action<bool> OnBool;
        public Action<float> OnFloat;
        public Action<GameObject> OnGame;
        public Action<int> OnInt;
        public Action<JSONObject> OnObj;
        public Action<object> OnObject;
        public Action<string> OnStr;
    }

    public interface NodeComponent
    {
        string GetKey();
        void OnInit();
        void OnDestroy();
    }

    public interface NodePage
    {
        void OnInit();
        void OnDestroy();
    }

    internal class UIAction
    {
        public Action<string> changeStr;
        public Action<string, string> changeStrKey;
        public Action<int, string> changeStrIndex;
        public Action<bool> changeBool;
        public Action<string, bool> changeBoolKey;
        public Action<int, bool> changeBoolIndex;
        public Action<float> changeFloat;
        public Action<string, float> changeFloatKey;
        public Action<int, float> changeFloatIndex;
        public Action<int> changeInt;
        public Action<string, int> changeIntKey;
        public Action<int, int> changeIntIndex;
        public Action<JSONObject> changeObj;
        public Action<string, JSONObject> changeObjKey;
        public Action<int, JSONObject> changeObjIndex;
        public Action<JSONArray> changeArr;
        public Action<string, JSONArray> changeArrKey;
        public Action<int, JSONArray> changeArrIndex;

        public Action click;
        public Action<string> clickData;
        public Action<string, string> clickDataKey;
        public Action<GameObject> clickGame;
        public Action<int> clickIndex;
        public Action<string, int> clickIndexKey;
        public Action<JSONObject> clickObj;
        public Dictionary<UIEvent, Action> eventAction;
        public Dictionary<UIEvent, Action<int>> eventIndexAction;
        public Dictionary<UIEvent, Action<string>> eventKeyAction;
    }

    public class BasePage
    {
        private readonly Dictionary<string, UIAction> actionMap = new();

        private Action<string, string> changeStr;
        private Action<string, string, string> changeStrKey;
        private Action<string, int, string> changeStrIndex;
        private Action<string, bool> changeBool;
        private Action<string, string, bool> changeBoolKey;
        private Action<string, int, bool> changeBoolIndex;
        private Action<string, float> changeFloat;
        private Action<string, string, float> changeFloatKey;
        private Action<string, int, float> changeFloatIndex;
        private Action<string, int> changeInt;
        private Action<string, string, int> changeIntKey;
        private Action<string, int, int> changeIntIndex;
        private Action<string, JSONObject> changeObj;
        private Action<string, string, JSONObject> changeObjKey;
        private Action<string, int, JSONObject> changeObjIndex;
        private Action<string, JSONArray> changeArr;
        private Action<string, string, JSONArray> changeArrKey;
        private Action<string, int, JSONArray> changeArrIndex;

        private Action<string> click;
        private Action<string, string> clickData;
        private Action<string, string, string> clickDataKey;
        private Action<string, GameObject> clickGame;
        private Action<string, int> clickIndex;
        private Action<string, string, int> clickIndexKey;
        private Action<string, JSONObject> clickObj;
        private readonly Dictionary<string, NodeComponent> componentMap = new();
        private Action<string> error;

        private Action<string, UIEvent> eventAction;
        private Action<string, UIEvent, int> eventIndexAction;
        private Action<string, UIEvent, string> eventKeyAction;

        private readonly Dictionary<SystemValue, EasyAction> eventMap = new();

        private Action<string, string, string> log;
        private readonly Dictionary<SystemValue, EasyAction> messageMap = new();

        private bool needRefresh;
        private readonly List<string> needRefreshChildList = new();
        public JSONObject param;
        public string PrevScene;
        private readonly Dictionary<string, Action> refreshMap = new();
        private NodeHelper Root;
        private NodePage rootPage;
        private readonly Dictionary<string, Action> roundMap = new();
        public JSONObject state;
        private readonly List<Action> syncList = new();
        private Action taskCb;
        private string taskKey;
        public float time;

        public BasePage()
        {
            state = new JSONObject();
        }

        public void Update()
        {
            time = Time.time;
            if (needRefresh)
            {
                if (Root != null && state != null) Root.SetData(state);
                needRefresh = false;
                needRefreshChildList.Clear();
            }

            if (needRefreshChildList.Count > 0)
            {
                HashSet<string> unique = new HashSet<string>(needRefreshChildList);
                string[] uniques = unique.ToArray();
                for (var i = 0; i < uniques.Length; i++)
                {
                    if (refreshMap.ContainsKey(uniques[i]))
                        refreshMap[uniques[i]]();
                }
                needRefreshChildList.Clear();
            }

            if (syncList.Count > 0)
            {
                foreach (var sync in syncList) sync();

                syncList.Clear();
            }

            foreach (var action in roundMap.Values) action();
        }

        public void Destroy()
        {
            foreach (var component in componentMap.Values) component.OnDestroy();

            componentMap.Clear();

            rootPage?.OnDestroy();
        }

        public void RegisterRootPage(NodePage page, JSONObject data)
        {
            page.OnInit();
            rootPage = page;
            state = data;
        }

        public void RegisterComponent(NodeComponent component, JSONObject data)
        {
            component.OnInit();
            state[component.GetKey()] = data;
            componentMap.Add(component.GetKey(), component);
        }

        public void BindNode(NodeHelper node)
        {
            LogTools.Process("BindNode");
            Root = node;
            BindEvent();
            OnRefresh();
            RefreshUI();
        }

        public void RefreshUI()
        {
            needRefresh = true;
        }

        public void RefreshChildUI(string key)
        {
            needRefreshChildList.Add(key);
        }

        public void RefreshChildUI(NodeComponent component)
        {
            needRefreshChildList.Add(component.GetKey());
        }

        public void Sync(Action action)
        {
            syncList.Add(action);
        }

        public void Round(string key, Action action)
        {
            roundMap.Add(key, action);
        }

        public void CancelRound(string key)
        {
            roundMap.Remove(key);
        }

        public void StartTask(string key, Action cb)
        {
            taskKey = key;
            taskCb = cb;
        }

        public void StopTask(string key)
        {
            if (key == taskKey && taskCb != null)
            {
                taskCb();
                taskCb = null;
            }
        }

        /// <summary>
        ///     action
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private UIAction GetAction(string key)
        {
            UIAction a;
            if (actionMap.ContainsKey(key))
            {
                a = actionMap[key];
            }
            else
            {
                a = new UIAction();
                actionMap.Add(key, a);
            }

            return a;
        }

        private void OnRefresh()
        {
            Root.OnRefresh((key, refresh) =>
            {
                if (refreshMap.ContainsKey(key))
                    refreshMap[key] = refresh;
                else
                    refreshMap.Add(key, refresh);
            });
        }

        public void Log(string type, string category, string value)
        {
            if (log != null) log(type, category, value);
        }

        public void OnLog(Action<string, string, string> action)
        {
            if (log == null) log = (type, category, value) => { action(type, category, value); };
        }

        public void Error(string err)
        {
            if (error != null) error(err);
        }

        public void OnError(Action<string> action)
        {
            if (error == null) error = err => { action(err); };
        }

        public void Event(string k, UIEvent e)
        {
            if (eventAction != null) eventAction(k, e);
        }

        public void OnEvent(string k, UIEvent e, Action action)
        {
            if (eventAction == null)
                eventAction = (s, ui) =>
                {
                    var u = GetAction(s);
                    if (u.eventAction != null && u.eventAction.ContainsKey(ui)) u.eventAction[ui]();
                };
            var a = GetAction(k);
            if (a.eventAction == null) a.eventAction = new Dictionary<UIEvent, Action>();
            a.eventAction.Add(e, action);
        }

        public void Event(string k, UIEvent e, string key)
        {
            if (eventKeyAction != null) eventKeyAction(k, e, key);
        }

        public void OnEvent(string k, UIEvent e, Action<string> action)
        {
            if (eventKeyAction == null)
                eventKeyAction = (s, ui, key) =>
                {
                    var u = GetAction(s);
                    if (u.eventKeyAction != null && u.eventKeyAction.ContainsKey(ui)) u.eventKeyAction[ui](key);
                };
            var a = GetAction(k);
            if (a.eventKeyAction == null) a.eventKeyAction = new Dictionary<UIEvent, Action<string>>();
            a.eventKeyAction.Add(e, action);
        }

        public void Event(string k, UIEvent e, int index)
        {
            if (eventIndexAction != null) eventIndexAction(k, e, index);
        }

        public void OnEvent(string k, UIEvent e, Action<int> action)
        {
            if (eventIndexAction == null)
                eventIndexAction = (s, ui, index) =>
                {
                    var u = GetAction(s);
                    if (u.eventIndexAction != null && u.eventIndexAction.ContainsKey(ui)) u.eventIndexAction[ui](index);
                };
            var a = GetAction(k);
            if (a.eventIndexAction == null) a.eventIndexAction = new Dictionary<UIEvent, Action<int>>();
            a.eventIndexAction.Add(e, action);
        }

        public void Click(string k)
        {
            if (click != null) click(k);
        }

        public void OnClick(string k, Action action)
        {
            if (click == null)
                click = s =>
                {
                    var u = GetAction(s);
                    if (u.click != null) u.click();
                };
            var a = GetAction(k);
            a.click = action;
        }

        public void Click(string k, int index)
        {
            if (clickIndex != null) clickIndex(k, index);
        }

        public void OnClick(string k, Action<int> action)
        {
            if (clickIndex == null)
                clickIndex = (s, i) =>
                {
                    var u = GetAction(s);
                    if (u.clickIndex != null) u.clickIndex(i);
                };
            var a = GetAction(k);
            a.clickIndex = action;
        }

        public void Click(string k, string d)
        {
            if (clickData != null) clickData(k, d);
        }

        public void OnClick(string k, Action<string> action)
        {
            if (clickData == null)
                clickData = (s, d) =>
                {
                    var u = GetAction(s);
                    if (u.clickData != null) u.clickData(d);
                };
            var a = GetAction(k);
            a.clickData = action;
        }

        public void Click(string k, GameObject obj)
        {
            if (clickGame != null) clickGame(k, obj);
        }

        public void OnClick(string k, Action<GameObject> action)
        {
            if (clickGame == null)
                clickGame = (s, o) =>
                {
                    var u = GetAction(s);
                    if (u.clickGame != null) u.clickGame(o);
                };
            var a = GetAction(k);
            a.clickGame = action;
        }

        public void Click(string k, JSONObject obj)
        {
            if (clickObj != null) clickObj(k, obj);
        }

        public void OnClick(string k, Action<JSONObject> action)
        {
            if (clickObj == null)
                clickObj = (s, o) =>
                {
                    var u = GetAction(s);
                    if (u.clickObj != null) u.clickObj(o);
                };
            var a = GetAction(k);
            a.clickObj = action;
        }

        public void Click(string k, string s1, string s2)
        {
            if (clickDataKey != null) clickDataKey(k, s1, s2);
        }

        public void OnClick(string k, Action<string, string> action)
        {
            if (clickDataKey == null)
                clickDataKey = (s, s1, s2) =>
                {
                    var u = GetAction(s);
                    if (u.clickDataKey != null) u.clickDataKey(s1, s2);
                };
            var a = GetAction(k);
            a.clickDataKey = action;
        }

        public void Click(string k, string d, int i)
        {
            if (clickIndexKey != null) clickIndexKey(k, d, i);
        }

        public void OnClick(string k, Action<string, int> action)
        {
            if (clickIndexKey == null)
                clickIndexKey = (s, s1, s2) =>
                {
                    var u = GetAction(s);
                    if (u.clickIndexKey != null) u.clickIndexKey(s1, s2);
                };
            var a = GetAction(k);
            a.clickIndexKey = action;
        }

        public void Change(string k, string d)
        {
            if (changeStr != null) changeStr(k, d);
        }

        public void OnChange(string k, Action<string> action)
        {
            if (changeStr == null)
                changeStr = (ks, s) =>
                {
                    var u = GetAction(ks);
                    if (u.changeStr != null) u.changeStr(s);
                };
            var a = GetAction(k);
            a.changeStr = action;
        }

        public void Change(string k, float f)
        {
            if (changeFloat != null) changeFloat(k, f);
        }

        public void OnChange(string k, Action<float> action)
        {
            if (changeFloat == null)
                changeFloat = (ks, f) =>
                {
                    var u = GetAction(ks);
                    if (u.changeFloat != null) u.changeFloat(f);
                };
            var a = GetAction(k);
            a.changeFloat = action;
        }

        public void Change(string k, bool b)
        {
            if (changeBool != null) changeBool(k, b);
        }

        public void OnChange(string k, Action<bool> action)
        {
            if (changeBool == null)
                changeBool = (ks, b) =>
                {
                    var u = GetAction(ks);
                    if (u.changeBool != null) u.changeBool(b);
                };
            var a = GetAction(k);
            a.changeBool = action;
        }

        public void Change(string k, int i)
        {
            if (changeInt != null) changeInt(k, i);
        }

        public void OnChange(string k, Action<int> action)
        {
            if (changeInt == null)
                changeInt = (ks, i) =>
                {
                    var u = GetAction(ks);
                    if (u.changeInt != null) u.changeInt(i);
                };
            var a = GetAction(k);
            a.changeInt = action;
        }

        public void Change(string k, JSONObject obj)
        {
            if (changeObj != null) changeObj(k, obj);
        }

        public void OnChange(string k, Action<JSONObject> action)
        {
            if (changeObj == null)
                changeObj = (ks, obj) =>
                {
                    var u = GetAction(ks);
                    if (u.changeObj != null) u.changeObj(obj);
                };
            var a = GetAction(k);
            a.changeObj = action;
        }

        public void Change(string k, JSONArray arr)
        {
            if (changeArr != null) changeArr(k, arr);
        }

        public void OnChange(string k, Action<JSONArray> action)
        {
            if (changeArr == null)
                changeArr = (ks, arr) =>
                {
                    var u = GetAction(ks);
                    if (u.changeArr != null) u.changeArr(arr);
                };
            var a = GetAction(k);
            a.changeArr = action;
        }

        public void Change(string k, string kk, string d)
        {
            if (changeStrKey != null) changeStrKey(k, kk, d);
        }

        public void OnChange(string k, Action<string, string> action)
        {
            if (changeStrKey == null)
                changeStrKey = (ks, kk, s) =>
                {
                    var u = GetAction(ks);
                    if (u.changeStrKey != null) u.changeStrKey(kk, s);
                };
            var a = GetAction(k);
            a.changeStrKey = action;
        }

        public void Change(string k, string kk, float f)
        {
            if (changeFloatKey != null) changeFloatKey(k, kk, f);
        }

        public void OnChange(string k, Action<string, float> action)
        {
            if (changeFloatKey == null)
                changeFloatKey = (ks, kk, f) =>
                {
                    var u = GetAction(ks);
                    if (u.changeFloatKey != null) u.changeFloatKey(kk, f);
                };
            var a = GetAction(k);
            a.changeFloatKey = action;
        }

        public void Change(string k, string kk, bool b)
        {
            if (changeBoolKey != null) changeBoolKey(k, kk, b);
        }

        public void OnChange(string k, Action<string, bool> action)
        {
            if (changeBoolKey == null)
                changeBoolKey = (ks, kk, b) =>
                {
                    var u = GetAction(ks);
                    if (u.changeBoolKey != null) u.changeBoolKey(kk, b);
                };
            var a = GetAction(k);
            a.changeBoolKey = action;
        }

        public void Change(string k, string kk, int b)
        {
            if (changeIntKey != null) changeIntKey(k, kk, b);
        }

        public void OnChange(string k, Action<string, int> action)
        {
            if (changeIntKey == null)
                changeIntKey = (ks, kk, i) =>
                {
                    var u = GetAction(ks);
                    if (u.changeIntKey != null) u.changeIntKey(kk, i);
                };
            var a = GetAction(k);
            a.changeIntKey = action;
        }

        public void Change(string k, string kk, JSONObject obj)
        {
            if (changeObjKey != null) changeObjKey(k, kk, obj);
        }

        public void OnChange(string k, Action<string, JSONObject> action)
        {
            if (changeObjKey == null)
                changeObjKey = (ks, kk, obj) =>
                {
                    var u = GetAction(ks);
                    if (u.changeObjKey != null) u.changeObjKey(kk, obj);
                };
            var a = GetAction(k);
            a.changeObjKey = action;
        }

        public void Change(string k, string kk, JSONArray arr)
        {
            if (changeArrKey != null) changeArrKey(k, kk, arr);
        }

        public void OnChange(string k, Action<string, JSONArray> action)
        {
            if (changeArrKey == null)
                changeArrKey = (ks, kk, arr) =>
                {
                    var u = GetAction(ks);
                    if (u.changeArrKey != null) u.changeArrKey(kk, arr);
                };
            var a = GetAction(k);
            a.changeArrKey = action;
        }

        public void Change(string k, int i, string d)
        {
            if (changeStrIndex != null) changeStrIndex(k, i, d);
        }

        public void OnChange(string k, Action<int, string> action)
        {
            if (changeStrIndex == null)
                changeStrIndex = (ks, index, s) =>
                {
                    var u = GetAction(ks);
                    if (u.changeStrIndex != null) u.changeStrIndex(index, s);
                };
            var a = GetAction(k);
            a.changeStrIndex = action;
        }

        public void Change(string k, int i, float f)
        {
            if (changeFloatIndex != null) changeFloatIndex(k, i, f);
        }

        public void OnChange(string k, Action<int, float> action)
        {
            if (changeFloatIndex == null)
                changeFloatIndex = (ks, index, f) =>
                {
                    var u = GetAction(ks);
                    if (u.changeFloatIndex != null) u.changeFloatIndex(index, f);
                };
            var a = GetAction(k);
            a.changeFloatIndex = action;
        }

        public void Change(string k, int i, bool b)
        {
            if (changeBoolIndex != null) changeBoolIndex(k, i, b);
        }

        public void OnChange(string k, Action<int, bool> action)
        {
            if (changeBoolIndex == null)
                changeBoolIndex = (ks, index, b) =>
                {
                    var u = GetAction(ks);
                    if (u.changeBoolIndex != null) u.changeBoolIndex(index, b);
                };
            var a = GetAction(k);
            a.changeBoolIndex = action;
        }

        public void Change(string k, int i, int b)
        {
            if (changeIntIndex != null) changeIntIndex(k, i, b);
        }

        public void OnChange(string k, Action<int, int> action)
        {
            if (changeIntIndex == null)
                changeIntIndex = (ks, index, i) =>
                {
                    var u = GetAction(ks);
                    if (u.changeIntIndex != null) u.changeIntIndex(index, i);
                };
            var a = GetAction(k);
            a.changeIntIndex = action;
        }

        public void Change(string k, int i, JSONObject obj)
        {
            if (changeObjIndex != null) changeObjIndex(k, i, obj);
        }

        public void OnChange(string k, Action<int, JSONObject> action)
        {
            if (changeObjIndex == null)
                changeObjIndex = (ks, index, obj) =>
                {
                    var u = GetAction(ks);
                    if (u.changeObjIndex != null) u.changeObjIndex(index, obj);
                };
            var a = GetAction(k);
            a.changeObjIndex = action;
        }

        public void Change(string k, int i, JSONArray arr)
        {
            if (changeArrIndex != null) changeArrIndex(k, i, arr);
        }

        public void OnChange(string k, Action<int, JSONArray> action)
        {
            if (changeArrIndex == null)
                changeArrIndex = (ks, index, arr) =>
                {
                    var u = GetAction(ks);
                    if (u.changeArrIndex != null) u.changeArrIndex(index, arr);
                };
            var a = GetAction(k);
            a.changeArrIndex = action;
        }

        private void BindEvent()
        {
            if (eventAction != null) Root.On(eventAction);
            if (eventKeyAction != null) Root.On(eventKeyAction);
            if (eventIndexAction != null) Root.On(eventIndexAction);
            if (log != null) Root.OnLog(log);
            if (click != null) Root.OnClick(click);
            if (clickIndex != null) Root.OnClick(clickIndex);
            if (clickData != null) Root.OnClick(clickData);
            if (clickGame != null) Root.OnClick(clickGame);
            if (clickObj != null) Root.OnClick(clickObj);
            if (clickDataKey != null) Root.OnClick(clickDataKey);
            if (clickIndexKey != null) Root.OnClick(clickIndexKey);
            if (changeStr != null) Root.OnChange(changeStr);
            if (changeStrKey != null) Root.OnChange(changeStrKey);
            if (changeStrIndex != null) Root.OnChange(changeStrIndex);
            if (changeFloat != null) Root.OnChange(changeFloat);
            if (changeFloatKey != null) Root.OnChange(changeFloatKey);
            if (changeFloatIndex != null) Root.OnChange(changeFloatIndex);
            if (changeBool != null) Root.OnChange(changeBool);
            if (changeBoolKey != null) Root.OnChange(changeBoolKey);
            if (changeBoolIndex != null) Root.OnChange(changeBoolIndex);
            if (changeInt != null) Root.OnChange(changeInt);
            if (changeIntKey != null) Root.OnChange(changeIntKey);
            if (changeIntIndex != null) Root.OnChange(changeIntIndex);
            if (changeObj != null) Root.OnChange(changeObj);
            if (changeObjKey != null) Root.OnChange(changeObjKey);
            if (changeObjIndex != null) Root.OnChange(changeObjIndex);
            if (changeArr != null) Root.OnChange(changeArr);
            if (changeArrKey != null) Root.OnChange(changeArrKey);
            if (changeArrIndex != null) Root.OnChange(changeArrIndex);
        }

        /// <summary>
        ///     message
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private EasyAction GetMessageAction(SystemValue key)
        {
            EasyAction a;
            if (messageMap.ContainsKey(key))
            {
                a = messageMap[key];
            }
            else
            {
                a = new EasyAction();
                messageMap.Add(key, a);
            }

            return a;
        }

        public void Send(SystemValue key)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.On != null) e.On();
        }

        public void Send(SystemValue key, object o)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnObject != null) e.OnObject(o);
        }

        public void Send(SystemValue key, string s)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnStr != null) e.OnStr(s);
        }

        public void Send(SystemValue key, bool b)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnBool != null) e.OnBool(b);
        }

        public void Send(SystemValue key, float f)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnFloat != null) e.OnFloat(f);
        }

        public void Send(SystemValue key, int i)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnInt != null) e.OnInt(i);
        }

        public void Send(SystemValue key, JSONObject obj)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnObj != null) e.OnObj(obj);
        }

        public void Send(SystemValue key, JSONArray arr)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnArr != null) e.OnArr(arr);
        }

        public void Send(SystemValue key, GameObject game)
        {
            var e = GetMessageAction(key);
            if (e == null) return;
            if (e.OnGame != null) e.OnGame(game);
        }

        public bool IsReceive(SystemValue key)
        {
            return messageMap.ContainsKey(key);
        }

        private void Receive(SystemValue key, EasyAction e)
        {
            messageMap[key] = e;
        }

        public void Receive(SystemValue key, Action action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.On = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<object> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnObject = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<string> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnStr = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<bool> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnBool = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<float> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnFloat = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<int> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnInt = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<JSONObject> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnObj = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<JSONArray> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnArr = action;
            Receive(key, e);
        }

        public void Receive(SystemValue key, Action<GameObject> action)
        {
            var e = GetMessageAction(key);
            if (e == null) e = new EasyAction();
            e.OnGame = action;
            Receive(key, e);
        }

        public bool IsOn(SystemValue key)
        {
            return eventMap.ContainsKey(key);
        }

        /// <summary>
        ///     Event
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private EasyAction GetEventAction(SystemValue key)
        {
            EasyAction a;
            if (eventMap.ContainsKey(key))
            {
                a = eventMap[key];
            }
            else
            {
                a = new EasyAction();
                eventMap.Add(key, a);
            }

            return a;
        }

        public void Trigger(SystemValue key)
        {
            var e = GetEventAction(key);
            if (e.On != null) e.On();
        }

        public void Trigger(SystemValue key, object o)
        {
            var e = GetEventAction(key);
            if (e.OnObject != null) e.OnObject(o);
        }

        public void Trigger(SystemValue key, string s)
        {
            var e = GetEventAction(key);
            if (e.OnStr != null) e.OnStr(s);
        }

        public void Trigger(SystemValue key, bool b)
        {
            var e = GetEventAction(key);
            if (e.OnBool != null) e.OnBool(b);
        }

        public void Trigger(SystemValue key, float f)
        {
            var e = GetEventAction(key);
            if (e.OnFloat != null) e.OnFloat(f);
        }

        public void Trigger(SystemValue key, int i)
        {
            var e = GetEventAction(key);
            if (e.OnInt != null) e.OnInt(i);
        }

        public void Trigger(SystemValue key, JSONObject obj)
        {
            var e = GetEventAction(key);
            if (e.OnObj != null) e.OnObj(obj);
        }

        public void Trigger(SystemValue key, JSONArray arr)
        {
            var e = GetEventAction(key);
            if (e.OnArr != null) e.OnArr(arr);
        }

        public void Trigger(SystemValue key, GameObject game)
        {
            var e = GetEventAction(key);
            if (e.OnGame != null) e.OnGame(game);
        }

        public void On(SystemValue key, Action action)
        {
            var e = GetEventAction(key);
            e.On = action;
        }

        public void On(SystemValue key, Action<object> action)
        {
            var e = GetEventAction(key);
            e.OnObject = action;
        }

        public void On(SystemValue key, Action<string> action)
        {
            var e = GetEventAction(key);
            e.OnStr = action;
        }

        public void On(SystemValue key, Action<bool> action)
        {
            var e = GetEventAction(key);
            e.OnBool = action;
        }

        public void On(SystemValue key, Action<float> action)
        {
            var e = GetEventAction(key);
            e.OnFloat = action;
        }

        public void On(SystemValue key, Action<int> action)
        {
            var e = GetEventAction(key);
            e.OnInt = action;
        }

        public void On(SystemValue key, Action<JSONObject> action)
        {
            var e = GetEventAction(key);
            e.OnObj = action;
        }

        public void On(SystemValue key, Action<JSONArray> action)
        {
            var e = GetEventAction(key);
            e.OnArr = action;
        }

        public void On(SystemValue key, Action<GameObject> action)
        {
            var e = GetEventAction(key);
            e.OnGame = action;
        }
    }
}